#ifndef _OCPP_GribVariable_H__
#define _OCPP_GribVariable_H__

#include "GribTime.h"
#include "GribLevel.h"
#include "OCMain/Log.h"
#include "OCVolume/GridVariable.h"


namespace OCPP
{
	using namespace Volume;

	struct InventoryEx
	{
		uint8 GribVersion;
		size_t start;
		uint16 msgNum;
		uint16 subgNum;
		time_t refTime;
		time_t validTime;
		time_t foreSec;
		String element;
		String comment;
		String unitName;
		String shortFstLevel;
		String longFstLevel;
		double level;
		double level2;
		String levelUnit;
		String refTimeStr;
		String validTimeStr;
		IntVector Grib2_Parameter;
	};

	using InventoryVector = std::vector<std::shared_ptr<InventoryEx> >;
	using InventoryMap = std::map<String, std::shared_ptr<InventoryEx> >;
	using doubleMap = std::map<double, double>;

	inline int compareByLevelDown(const std::shared_ptr<InventoryEx>& lefObj, const std::shared_ptr<InventoryEx>& rhObj)
	{
		return lefObj->level - rhObj->level > 0.0 ? 1 : 0;
	}

	inline int compareByLevelUp(const std::shared_ptr<InventoryEx>& lefObj, const std::shared_ptr<InventoryEx>& rhObj)
	{
		return lefObj->level - rhObj->level < 0.0 ? 1 : 0;
	}

	inline int compareByTime(const std::shared_ptr<InventoryEx>& lefObj, const std::shared_ptr<InventoryEx>& rhObj)
	{
		return lefObj->validTime - rhObj->validTime < 0.0 ? 1 : 0;
	}

	using GribLevelIndex = std::tuple<GribLevel, size_t>;
	using GribLevelIndexVec = std::vector<GribLevelIndex>;
	using GribTimeMap = std::map<GribTime, GribLevelIndexVec>;

	class GribVariable : public Volume::GridVariable
	{
	public:
		void insert(std::shared_ptr<InventoryEx> inv);
		int size() { return (int)mInventoryVector.size(); }
		void setName(String name) { mName = name; }

		const String description();

		int getTimeSize() { return (int)_gribTimeMap.size(); }

		std::shared_ptr<InventoryEx> getInventor(size_t i) {
			return mInventoryVector[i];
		}

		GribTimeVec getTimeVec();
		const GribLevelIndexVec& getLevelVec(GribTime time);

		//
		void afterSetDimXY(VarData& varData);

		const GribLevelIndexVec& getLevelVecByTime(int i);

		virtual GridVariablePtr findDimVariable(String name);
		virtual StringVector getDims();
		virtual GridShape getShape();
		virtual String getName() { return mName; }
		virtual String getTimeString(int index) { return ""; }
		virtual String getUnitsString() { return ""; }
		virtual FloatVector readFloat() { return FloatVector(); }

		FloatVector _lonValues, _latValues;
		GribSyncFileWeakPtr gridSyncFilePtr;
	private:

		GribTimeMap _gribTimeMap;

		std::map<IntVector, InventoryVector> mGribParameter;

		String			mName;
		doubleMap		mLevelMap;
		DoubleVector	mLevelVector;

		StringMap		mLevelBoundMap;
		StringVector	mLevelBoundVector;

		StringMap		mTimeMap;
		StringVector	mTimeVector;
		InventoryVector mInventoryVector;
	};

	struct GribReadIndex
	{
		std::shared_ptr<GribVariable> _var;		
		GribTime _time;
		int _level;
	};

	using GribReadIndexList = std::vector<GribReadIndex>;
}


#endif // !_OCPP_GribReader_H__
